#ifndef _ITEM_HPP_
#define	_ITEM_HPP_
/*******************************************************************************
 ** Name: item.hpp                                                            **
 ** Description: WorldObject-derived container objects                        **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the LICENSE file within             **
 ** this distribution or at $WIKI/display/GOVT/License-software.              **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $GAME_DIR/LICENSE.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 ** Copyright (c) 2009-2011  Barry Gian James <gian@gamingods.net>            **
 ** All rights reserved.                                                      **
 ******************************************************************************/
// Portions (c) 2012 Open Design Strategies, LLC.
// Modified $Date$ by $Author$

#define Item_hpp_ID   "$Id$"

#include "object.hpp"

#pragma db object table("item_category")
struct ItemCategoryTable
{
	ItemCategoryTable() { }

#pragma db id auto
	entity_t	_iditem_category;
#pragma db type ("VARCHAR(16)")
	std::string	_name;
#pragma db type("CHAR(1)")
	char		_abbr;
};

#pragma db object table("item_type")
struct  ItemTypeTable
{
	ItemTypeTable() { }

#pragma db id auto
	entity_t	_iditem_type;
#pragma db type ("VARCHAR(16)")
	std::string	_name;
};

enum class ItemType
{
	Unknown,
	Jewelry, Common, Consumable, Toxic, Decoration, Resource, Scratch,
	Container, Weapon, Device, Gear, Book, Recipe
};

enum class ItemCategory
{
	Unknown,
	Technology, Support, Gadget, Tradecraft, Resource,
	Protective, Vehicle, Weapon
};

enum class TierGrade : ushort
{
	Undefined, I, II, III, IV, V, VI, VII, VIII, IX, X
};
//extern const char * ItemTypeStr[];

// Item flags
#define ITEM_WEARABLE	0x00000001
#define ITEM_WEAR_HEAD	0x00000002
#define ITEM_WEAR_NECK 0x00000004
#define ITEM_WEAR_TORSO 0x00000008
#define ITEM_WEAR_BACK 0x000000010
#define ITEM_WEAR_RWRIST 0x00000020
#define ITEM_WEAR_LWRIST 0x00000040
#define ITEM_WEAR_LFINGER 0x00000080
#define ITEM_WEAR_RFINGER 0x00000100
#define ITEM_WEAR_LEGS 0x00000200
#define ITEM_WEAR_WAIST 0x00000400
#define ITEM_WEAR_FEET	 0x00000800
#define ITEM_WEAR_HANDS 0x00001000
#define ITEM_STACKABLE	 0x00002000
#define ITEM_DROPABLE   0x00004000
#define ITEM_SELLABLE	 0x00008000
#define ITEM_UNIQUE		0x00010000
#define ITEM_WIELDABLE	0x00020000
#define ITEM_AUCTIONABLE 0x00040000
#define ITEM_UNBREAKABLE 0x00080000
#define ITEM_TRADEABLE	 0x00100000
#define ITEM_CAN_STEAL	 0x00200000
#define ITEM_NO_DECAY	 0x00400000
#define ITEM_GADGET		 0x00800000
#define ITEM_CAN_MAIL	 0x01000000
#define ITEM_BIND_EQUIP	 0x02000000
#define ITEM_LVL_ADJUST  0x04000000
#define ITEM_BIND_PICKUP 0x08000000

enum class ItemFlag
{
	Wearable = 1, Head, Neck, Torso, Back, RWrist, LWrist,
	LFinger, RFinger, Legs, Waist, Feet, Hands, Stackable,
	Dropable, Sellable, Unique, Wieldable, Auctionable,
	Unbreakable, Tradeable, Stealable, NoDecay, Gadget,
	CanMail, BindEquip, LevelAdjust, BindPickup
};

typedef EnumFlag<ItemFlag> ItemFlags;
#pragma db value(ItemFlags) type("BIGINT")

enum class ItemRestriction
{
	Unknown,
	None, Licensed, LawEnforcement, Government,
	Military, Banned
};
#pragma db object table("restrictions")
struct ItemRestrictionTable
{
#pragma db id auto
	entity_t	idrestrictions_;
#pragma db type ("VARCHAR(16)")
	std::string name_;
};



// An ItemTemplate is a non-instantiated item object that is used to build
// or create or instantiate new objects that that type wit standard values
#pragma db object table("item_templates")
struct ItemTemplate
{
	ItemTemplate() { }

//#pragma db id auto
//	entity_t		id_;
#pragma db type ("VARCHAR(64)")
	std::string		name_;
#pragma db id type ("VARCHAR(64)")
	std::string		tag_;
	ushort			weight_;
	unsigned int	value_;
#pragma db type ("VARCHAR(16)")
	std::string		idrestriction_;
	std::string		desc_;
	ushort			durability_max_;
	ushort			upgrade_slots_;
	ushort			dmg_save_;
	unsigned int	xp_;
	ushort			complexity_;
	TierGrade		tier_;
	char		idcategory_;
//#pragma db id_type("VARCHAR(16)")
	char		idsize_;
#pragma db type ("VARCHAR(50)")
	std::string		idtype_;
#pragma db type ("VARCHAR(50)")
	std::string idsubtype;
#pragma db unordered
	std::vector<entity_t> traits_;
#pragma db unordered
	std::vector<entity_t> aka_;
	EnumFlag<ItemFlag> flags_;
//	uint64_t		flags_;
};


//! @class Item
//! @brief Base class for all "items" in the game except wearable, magic, weapons
#pragma db object polymorphic pointer(boost::shared_ptr) table("items")
class Item : public WorldObject
{
public:
	SMART_PTR_DECL(Item);

	Item() : WorldObject() { }
    Item(const std::string & n, const std::string & t);
    Item(ObjectType tt, const std::string & n, const std::string & t);
    Item(const Item& orig);
    virtual ~Item() { }

    // Getters
    const entity_t 	Creator() const { return _idcreator; }
    const ushort 	DmgSave() const { return _dmg_save; }
    const ushort 	Complexity() const { return _complexity; }
    const ushort 	Durability() const { return _durability; }
    const ushort 	DurabilityMax() const { return _durability_max; }
    const double 	DurabilityDecay() const { return _durability_decay; }
    const ushort	StackAmount() const { return _stack_amount; }
    const unsigned int 		Value() const { return _value; }
    const ushort 	ErrorRange() const { return _error_range; }
    const ushort 	ThreatRange() const { return _threat_range; }
    const char  Category() const { return _idcategory; }
    const std::string &  Restriction() const { return _idrestriction; }
    const unsigned int 	WearLocations() const { return _wear_locs; }
    const unsigned int 	WearLocation() const { return _wear_loc; }
    const std::string &  Type() const { return _idtype; }
    const TierGrade		Tier() const { return _tier; }
    const std::vector<entity_t> & Traits() const { return traits_; }
    const std::string & SubType() const { return _idsubtype; }

    // Setters
    void	Creator(const entity_t c) { _idcreator = c; }
    void	DmgSave(const ushort s) { _dmg_save = s; }
    void	Complexity(const ushort c) { _complexity = c; }
    void	Durability(const ushort d) { _durability = d; }
    void	DurabilityMax(const ushort d) { _durability_max = d; }
    void	DurabilityDecay(const double d) { _durability_decay = d; }
    void	StackAmount(const ushort s) { _stack_amount = s; }
    void	Value(const unsigned int c) { _value = c; }
    void	ErrorRange(const ushort r) { _error_range = r; }
    void	ThreatRange(const ushort r) { _threat_range = r; }
    void	Category(const char  c) { _idcategory = c; }
    void	Restriction(const std::string & r) { _idrestriction = r; }
    void	WearLocations(const unsigned int wl) { _wear_locs = wl; }
    void	WearLocation(const unsigned int wl) { _wear_loc = wl; }
    void	Type(const std::string &  t) { _idtype = t; }
    void	SubType(const std::string &  t) { _idsubtype = t; }
    void	Tier(const TierGrade & t) { _tier = t; }
    void	Traits(const entity_t t) { traits_.push_back(t); }

    bool		Dropable() { return Flags() & ITEM_DROPABLE; }
    bool		Stackable() { return Flags() & ITEM_STACKABLE; }
    bool		Wearable() { return Flags() & ITEM_WEARABLE; }
    bool		Unique() { return Flags() & ITEM_UNIQUE; }
    bool		Sellable() { return Flags() & ITEM_SELLABLE; }

    // Events
    virtual void		OnEquip() { }
    virtual void		OnUnequip() { }

protected:
    entity_t	_idcreator;
    ushort		_dmg_save;
    ushort		_complexity;
    ushort		_durability;
    ushort		_durability_max;
    double		_durability_decay;
    ushort		_stack_amount;
    unsigned int			_value;
    ushort		_error_range;	// between 0 - error_range
    ushort		_threat_range;	// between threat_range - 20
    char 		_idcategory;
#pragma db type ("VARCHAR(16)")
    std::string	_idrestriction;
#pragma db type ("VARCHAR(16)")
    std::string		_idtype;
#pragma db type ("VARCHAR(32)")
    std::string _idsubtype;
    unsigned int	_wear_locs;	// places this item can be worn
    unsigned int _wear_loc;		// actual place its worn, if at all
    ushort		_idsize;
    TierGrade	_tier;
#pragma db unordered
    std::vector<entity_t> traits_;
};

//! @class Device
//! @brief A specific Item derivation for security/electronic devices
#pragma db object table("devices")
class Device : public Item
{
public:
	Device();
	Device(const Device &);

private:
	friend class odb::access;

	ushort		_pr;
	ushort		_disable_dc;
	ushort		_detect_dc;
	int			_xp;
};

#endif	/* _ITEM_HPP_ */

